# 二、生成器对象
# 生成器本质上也是一种迭代器，是一种特殊的迭代器。
# 生成器是一个包含yield关键字的函数，当它被调用时，在函数体内的代码不会被执行，
# 而是返回一个(生成器）迭代器，每次(next)请求一个值，就会执行生成器中的代码，直到遇到一个yield或者return语句。
# yield语句意味着生成一个值，return语句意味着生成器要停止执行（不在生成任何东西）

def genarator_fuc():
    v1 = yield 1
    print(f'第一次传给生成器的值{v1}')
    v2 = yield 2
    print('hello')
    print(f'第二次传给生成器的值{v2}')
    v3 = yield 3
    print(f'第三次传给生成器的值{v3}')
    v4 = yield 4
    print(f'第四次传给生成器的值{v4}')
    v5 = yield 5
    print(f'第五次传给生成器的值{v5}')



g = genarator_fuc() # 创建一个生成器
# hasattr() 查看一个对象 有哪些函数， g 满足迭代器的定义。是一个迭代器。
# print(hasattr(g, '__iter__')) # True
# print(hasattr(g, '__next__')) # True

# print(g.__next__()) # 返回 1
# print(g.__next__()) # 返回 2
# print(g.__next__()) # 返回 3
# print(g.__next__()) # 返回 4
# print(g.__next__()) # 返回 5
# print(g.__next__()) # 第6个 next调用抛出异常 StopIteration

print(next(g)) # 返回
print(g.send(100)) #
# print(g.send(200)) #
# print(g.send(300)) #
# print(g.send(400)) #
# print(g.send(500)) #


# 调用 send函数
# g.send(100)
# g.send(200)
# g.send(300)
# g.send(400)
# g.send(500)

# 总结：
# 1. yield 把函数变成了一个生成器。
# 2. 调用该函数的时候不会立即执行代码，而是返回了一个生成器对象
# 3. 当使用 next() (在 for 循环中会自动调用 next() ) 作用于返回的生成器对象时，函数 开始执行，
#    在遇到 yield 的时候会『暂停』，并返回当前的迭代值；
# 4. 当再次使用 next() 的时候，函数会从原来『暂停』的地方继续执行，直到遇到 yield语 句，
#    如果没有 yield 语句，则抛出异常；
# 5. 生成器函数的执行过程看起来就是不断地 =执行->中断->执行->中断的过程
# 6. send() 函数就是 next() 的功能，加上传值给 上次暂停的yield 。
# 7. close() 函数来关闭一个生成器。生成器被关闭后，再次调用 next() 函数，
#    不管能否遇到 yield 关键字，都会抛出 StopIteration 异常，